home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / gnat-3.05- / gnat-3 / gnat-3.05-i486-linux-elf-bin / rts / a-adaint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-07  |  13.8 KB  |  540 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                         GNAT COMPILER COMPONENTS                         */
  4. /*                                                                          */
  5. /*                             A - A D A I N T                              */
  6. /*                                                                          */
  7. /*                            $Revision: 1.60 $                             */
  8. /*                                                                          */
  9. /*                          C Implementation File                           */
  10. /*                                                                          */
  11. /*   Copyright (C) 1992,1993,1994,1995,1996 Free Software Foundation, Inc.  */
  12. /*                                                                          */
  13. /* GNAT is free software;  you can  redistribute it  and/or modify it under */
  14. /* terms of the  GNU General Public License as published  by the Free Soft- */
  15. /* ware  Foundation;  either version 2,  or (at your option) any later ver- */
  16. /* sion.  GNAT is distributed in the hope that it will be useful, but WITH- */
  17. /* OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY */
  18. /* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License */
  19. /* for  more details.  You should have  received  a copy of the GNU General */
  20. /* Public License  distributed with GNAT;  see file COPYING.  If not, write */
  21. /* to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, */
  22. /* MA 02111-1307, USA.                                                      */
  23. /*                                                                          */
  24. /* As a  special  exception,  if you  link  this file  with other  files to */
  25. /* produce an executable,  this file does not by itself cause the resulting */
  26. /* executable to be covered by the GNU General Public License. This except- */
  27. /* ion does not  however invalidate  any other reasons  why the  executable */
  28. /* file might be covered by the  GNU Public License.                        */
  29. /*                                                                          */
  30. /* GNAT was originally developed  by the GNAT team at  New York University. */
  31. /* It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). */
  32. /*                                                                          */
  33. /****************************************************************************/
  34.  
  35. /*  This file contains those routines named by Import pragmas in package    */
  36. /*  GNAT.OS_Lib. Many of the subprograms in OS_Lib import standard library  */
  37. /*  calls directly. This file contains all other routines.                  */
  38.  
  39. #include <sys/types.h>
  40. #include <sys/stat.h>
  41. #include <fcntl.h>
  42. #include <time.h>
  43. #include "config.h"  /* this may define MSDOS */
  44. #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
  45. #include <process.h>
  46. #include <string.h>
  47. #endif
  48. #include "a-adaint.h"
  49.  
  50. /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
  51.    defined in the current system. On DOS-like systems these flags control
  52.    whether the file is opened/created in text-translation mode (CR/LF in
  53.    external file mapped to LF in internal file), but in Unix-like systems,
  54.    no text translation is required, so these flags have no effect.
  55. */
  56.  
  57.  
  58. #if defined (__EMX__)
  59. #include <os2.h>
  60. #endif
  61.  
  62. #if defined (MSDOS)
  63. #include <dos.h>
  64. #endif
  65.  
  66. #ifndef O_BINARY
  67. #define O_BINARY 0
  68. #endif
  69.  
  70. #ifndef O_TEXT
  71. #define O_TEXT 0
  72. #endif
  73.  
  74. extern char *getenv ();
  75.  
  76.  
  77. void
  78. to_gm_time (p_time, p_year, p_month, p_day, p_hours, p_mins, p_secs)
  79.      time_t *p_time;
  80.      int *p_year, *p_month, *p_day, *p_hours, *p_mins, *p_secs;
  81. {
  82.   struct tm *res = gmtime (p_time);
  83.  
  84.   *p_year = res->tm_year;
  85.   *p_month = res->tm_mon;
  86.   *p_day = res->tm_mday;
  87.   *p_hours = res->tm_hour;
  88.   *p_mins = res->tm_min;
  89.   *p_secs = res->tm_sec;
  90. }
  91. /* Return the maximum file name length.  */
  92.  
  93. int
  94. Get_Maximum_File_Name_Length ()
  95. {
  96. #ifdef MSDOS
  97.   return 8;
  98. #else
  99.   return -1;
  100. #endif
  101. }
  102.  
  103. /* Return the default switch character.  */
  104.  
  105. char
  106. Get_Switch_Character ()
  107. {
  108.   /* Under MSDOS, the switch character is not normally a hyphen, but this is
  109.      the convention DJGPP uses. Similarly under OS2, the switch character is
  110.      not normally a hypen, but this is the convention EMX uses.
  111.    */
  112.   return '-';
  113. }
  114.  
  115. /* Return nonzero if file names are case sensitive.  */
  116.  
  117. int
  118. Get_File_Names_Case_Sensitive ()
  119. {
  120. #if defined (__EMX__) || defined (MSDOS)
  121.   return 0;
  122. #else
  123.   return 1;
  124. #endif
  125. }
  126.  
  127. char
  128. Get_Default_Identifier_Character_Set ()
  129. {
  130. #if defined (__EMX__) || defined (MSDOS)
  131.   return 'p';
  132. #else
  133.   return '1';
  134. #endif
  135. }
  136.  
  137. #if defined(__EMX__) || defined (MSDOS)
  138. char dirsep_char = '\\';
  139. #else
  140. char dirsep_char = '/';
  141. #endif
  142.  
  143. #if defined(__EMX__) || defined (MSDOS) || defined (WINNT)
  144. char pathsep_char = ';';
  145. #else
  146. char pathsep_char = ':';
  147. #endif
  148.  
  149. /* Return the suffix for object files; the argument, str, is assumed to point
  150.    to an array of at least 4 characters.  */
  151.  
  152. void
  153. Get_Object_Suffix (str)
  154.      char *str;
  155. {
  156.   /* Under MSDOS, the suffix for object files is not normally .o, but this is
  157.      the convention DJGPP uses. Similarly under OS/2, the suffix for object
  158.      files is not normally .o, but this is the convention EMX uses. */
  159.   strcpy (str, "o");
  160. }
  161.  
  162. /* Return the suffix for executable files; the argument, str, is assumed to
  163.    point to an array of at least 4 characters.  */
  164.  
  165. void
  166. Get_Executable_Suffix (str)
  167.      char *str;
  168. {
  169. #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
  170.   strcpy (str, ".exe");
  171. #else
  172.   strcpy (str, "");
  173. #endif
  174. }
  175.  
  176. int
  177. open_read (path, fmode)
  178.      char *path;
  179.      int fmode;
  180. {
  181.   int fd;
  182.  
  183.   if (fmode)
  184.     fd = open (path, O_RDONLY | O_TEXT);
  185.   else
  186.     fd = open (path, O_RDONLY | O_BINARY);
  187.  
  188.   return fd < 0 ? -1 : fd;
  189. }
  190.  
  191.  
  192. #if defined (__EMX__)
  193. #define PERM (S_IREAD | S_IWRITE)
  194. #else
  195. #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
  196. #endif
  197.  
  198. int
  199. open_rw (path, fmode)
  200.      char *path;
  201.      int  fmode;
  202. {
  203.   int fd;
  204.  
  205.   if (fmode)
  206.     fd = open (path, O_RDWR | O_TEXT, PERM);
  207.   else
  208.     fd = open (path, O_RDWR | O_BINARY, PERM);
  209.  
  210.   return fd < 0 ? -1 : fd;
  211. }
  212.  
  213. int
  214. open_create (path, fmode)
  215.      char *path;
  216.      int  fmode;
  217. {
  218.   int fd;
  219.  
  220.   if (fmode)
  221.     fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
  222.   else
  223.     fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, PERM);
  224.  
  225.   return fd < 0 ? -1 : fd;
  226. }
  227.  
  228. /*  Open a new file.  Return error (-1) if the file already exists. */
  229.  
  230. int
  231. open_new (path, fmode)
  232.      char *path;
  233.      int fmode;
  234. {
  235.   int fd;
  236.   if (fmode)
  237.     fd =  open (path, O_WRONLY | O_CREAT | O_EXCL | O_TEXT, PERM);
  238.   else
  239.     fd =  open (path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, PERM);
  240.  
  241.   return fd < 0 ? -1 : fd;
  242. }
  243.  
  244. /* Return the number of bytes in the specified file. */
  245.  
  246. long
  247. file_length (fd)
  248.      int fd;
  249. {
  250.   int ret;
  251.   struct stat statbuf;
  252.  
  253.   ret = fstat (fd, &statbuf);
  254.   if (ret || !S_ISREG (statbuf.st_mode))
  255.     return 0;
  256.  
  257.   return (statbuf.st_size);
  258. }
  259.  
  260. /* Return a GNAT time stamp given a file name.  */
  261.  
  262. time_t
  263. file_time_name (name)
  264.      char *name;
  265. {
  266.   struct stat statbuf;
  267.  
  268. #if defined (__EMX__) || defined (MSDOS)
  269.   int fd = open (name, O_RDONLY | O_BINARY);
  270.   time_t ret = file_time_fd (fd);
  271.   close (fd);
  272.   return ret;
  273.  
  274. #else
  275.  
  276.   int ret = stat (name, &statbuf);
  277.   return statbuf.st_mtime;
  278. #endif
  279. }
  280.  
  281. /* Return a GNAT time stamp given a file descriptor.  */
  282.  
  283. time_t
  284. file_time_fd (fd)
  285.      int fd;
  286. {
  287.   /* The following workaround code is due to the fact that under EMX and DJGPP
  288.      fstat attempts to convert time values to GMT rather than keep the actual
  289.      OS timestamp of the file. By using the OS2/DOS functions directly the GNAT
  290.      timestamp are independent of this behavior, which is desired to facilitate
  291.      the distribution of GNAT compiled libraries. */
  292.  
  293. #if defined (__EMX__) || defined (MSDOS)
  294. #ifdef __EMX__
  295.  
  296.   FILESTATUS fs;
  297.   int ret = DosQueryFileInfo (fd, 1, (unsigned char *) &fs,
  298.                 sizeof (FILESTATUS));
  299.  
  300.   unsigned file_year  = fs.fdateLastWrite.year;
  301.   unsigned file_month = fs.fdateLastWrite.month;
  302.   unsigned file_day   = fs.fdateLastWrite.day;
  303.   unsigned file_hour  = fs.ftimeLastWrite.hours;
  304.   unsigned file_min   = fs.ftimeLastWrite.minutes;
  305.   unsigned file_tsec  = fs.ftimeLastWrite.twosecs;
  306.  
  307. #else
  308.   struct ftime fs;
  309.   int ret = getftime (fd, &fs);
  310.  
  311.   unsigned file_year  = fs.ft_year;
  312.   unsigned file_month = fs.ft_month;
  313.   unsigned file_day   = fs.ft_day;
  314.   unsigned file_hour  = fs.ft_hour;
  315.   unsigned file_min   = fs.ft_min;
  316.   unsigned file_tsec  = fs.ft_tsec;
  317. #endif
  318.  
  319.   /* Calculate the seconds since epoch from the time components. First count
  320.      the whole days passed.  The value for years returned by the DOS and OS2
  321.      functions count years from 1980, so to compensate for the UNIX epoch which
  322.      begins in 1970 start with 10 years worth of days and add days for each
  323.      four year period since then. */
  324.  
  325.   time_t tot_secs;
  326.   int cum_days [12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  327.   int days_passed = 3652 + (file_year / 4) * 1461;
  328.   int years_since_leap = file_year % 4;
  329.   if      (years_since_leap == 1) days_passed += 366;
  330.   else if (years_since_leap == 2) days_passed += 731;
  331.   else if (years_since_leap == 3) days_passed += 1096;
  332.   if (file_year > 20) days_passed -= 1;
  333.   days_passed += cum_days [file_month - 1];
  334.   if (years_since_leap == 0 && file_year != 20
  335.       && file_month > 2) days_passed++;
  336.   days_passed += file_day - 1;
  337.  
  338.   /* OK - have whole days.  Multiply -- then add in other parts. */
  339.   tot_secs  = days_passed               * 86400;
  340.   tot_secs += file_hour   * 3600;
  341.   tot_secs += file_min * 60;
  342.   tot_secs += file_tsec * 2;
  343.  
  344.   return tot_secs;
  345.  
  346. #else
  347.   struct stat statbuf;
  348.   int ret = fstat (fd, &statbuf);
  349.   return statbuf.st_mtime;
  350. #endif
  351. }
  352.  
  353. void
  354. get_env_value_ptr (name, len, value)
  355.      char *name;
  356.      int *len;
  357.      char **value;
  358. {
  359.   *value = getenv (name);
  360.   if (!*value)
  361.     *len = 0;
  362.   else
  363.     *len = strlen (*value);
  364.  
  365.   return;
  366. }
  367.  
  368. int
  369. is_regular_file (name)
  370.      char *name;
  371. {
  372.   int ret;
  373.   struct stat statbuf;
  374.  
  375.   ret = stat (name, &statbuf);
  376.   return (!ret && S_ISREG (statbuf.st_mode));
  377. }
  378.  
  379. int
  380. is_directory (name)
  381.      char *name;
  382. {
  383.   int ret;
  384.   struct stat statbuf;
  385.  
  386.   ret = stat (name, &statbuf);
  387.   return (!ret && S_ISDIR (statbuf.st_mode));
  388. }
  389.  
  390. int
  391. portable_spawn (args)
  392.     char *args[];
  393. {
  394.   int status;
  395.   int finished;
  396.   int pid;
  397.  
  398. #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
  399.   if (spawnvp (P_WAIT, args [0], args) != 0)
  400.     return (4);
  401. #else
  402.   pid = fork ();
  403.   if (pid == -1)
  404.     return (4);
  405.   if (pid == 0) {
  406.     /* The child */
  407.     execv (args [0], args);
  408.     return (4);
  409.   }
  410.  
  411.   /* The parent */
  412.   finished = wait (&status);
  413.   if (finished != pid || status & 0xffff)
  414.     return 4;
  415. #endif
  416.   return 0;
  417. }
  418.  
  419. int
  420. portable_no_block_spawn (args)
  421.     char *args[];
  422. {
  423.   int pid = 0;
  424.  
  425. #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
  426.   /* ??? For PC machines I (Franco) don't know the system calls to
  427.      implement this routine. So I'll fake it as follows. This routine
  428.      will behave exactly like the blocking portable_spawn and will
  429.      systematically return a pid of 0 unless the spawned task did not
  430.      complete successfully, in which case we return a pid of -1.  To
  431.      synchronize with this the portable_wait below systematically
  432.      returns a pid of 0 and reports that the subprocess terminated
  433.      successfully. */
  434.  
  435.   if (spawnvp (P_WAIT, args [0], args) != 0)
  436.     return (-1);
  437. #else
  438.   pid = fork ();
  439.  
  440.   if (pid == 0) {
  441.     /* The child */
  442.     execv (args [0], args);
  443.     return (-1);
  444.   }
  445. #endif
  446.  
  447.   return pid;
  448. }
  449.  
  450. int
  451. portable_wait (process_status)
  452.     int *process_status;
  453. {
  454.   int status = 0;
  455.   int pid    = 0;
  456.  
  457. #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
  458.   /* ??? See corresponding comment in portable_no_block_spawn. */
  459.  
  460. #else
  461.   pid    = wait (&status);
  462.   status = status & 0xffff;
  463. #endif
  464.  
  465.   *process_status = status;
  466.   return pid;
  467. }
  468.  
  469. char *
  470. locate_exec (exec_name, path_val)
  471.      char *exec_name;
  472.      char *path_val;
  473. {
  474.   char *ptr, *ptr1;
  475.   int len;
  476.  
  477.   /* Handle absolute pathnames (DJGPP and EMX could have either '/' or '\') */
  478.   for (ptr = exec_name; *ptr && *ptr != '/' && *ptr != dirsep_char; ptr++);
  479.  
  480.   if (*ptr
  481. #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
  482.       || isalpha (exec_name [0]) && exec_name [1] == ':'
  483. #endif
  484.      ) {
  485.     /* leave room for possible .exe extension */
  486.     char exec_path[strlen (exec_name) + 5];
  487.  
  488.     strcpy (exec_path, exec_name);
  489.  
  490. #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
  491.     /* If .exe or .bat extension not specified, make it .exe */
  492.  
  493.     ptr = strstr (exec_path, ".exe");
  494.     ptr1 = strstr (exec_path, ".bat");
  495.     if ((ptr == NULL || strlen (ptr) != 4)
  496.         && (ptr1 == NULL || strlen (ptr1) != 4))
  497.       strcat (exec_path, ".exe");
  498. #endif
  499.     if (is_regular_file (exec_path))
  500.       return xstrdup(exec_path);
  501.  
  502.     return (char *)0;
  503.   }
  504.  
  505.   if (! path_val) return (char *) 0;
  506.  
  507.   {
  508.     /* The result has to be smaller than path_val + exec_name + .exe */
  509.     char exec_path[strlen (path_val) + strlen (exec_name) + 5];
  510.  
  511.     for (;;) {
  512.       for (; *path_val == pathsep_char ; path_val++)
  513.         ;
  514.       if (! *path_val) return (char *) 0;
  515.  
  516.       for (ptr = exec_path; *path_val && *path_val != pathsep_char; )
  517.         *ptr++ = *path_val++;
  518.  
  519.       ptr--;
  520.       if (*ptr != '/' && *ptr != dirsep_char) /* DJGPP could have either */
  521.         *++ptr = dirsep_char;
  522.  
  523.       strcpy (++ptr, exec_name);
  524.  
  525. #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
  526.       /* If .exe or .bat extension not specified, make it .exe */
  527.  
  528.       ptr = strstr (exec_path, ".exe");
  529.       ptr1 = strstr (exec_path, ".bat");
  530.       if ((ptr == NULL || strlen (ptr) != 4)
  531.           && (ptr1 == NULL || strlen (ptr1) != 4))
  532.         strcat (exec_path, ".exe");
  533. #endif
  534.       if (is_regular_file (exec_path))
  535.         return xstrdup(exec_path);
  536.     }
  537.   }
  538.   return (char *) 0;
  539. }
  540.